package common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xz.common.config.XzConfig;
import com.xz.common.exception.ServiceException;
import common.OCR.Base64Util;
import common.OCR.FileUtil;
import common.OCR.HttpUtil;
import common.OCR.PicUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.ObjectUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import net.coobird.thumbnailator.Thumbnails;

/**
 * @program: xzcz-v2.0.1
 * @description: 文字识别工具类
 * @author: Yan.Zhang
 * @create: 2020-06-12 10:00
 **/
@Slf4j
public class OCRUtils {

    /**
     * 获取API访问token
     * 该token有一定的有效期，需要自行管理，当失效时需重新获取.
     *
     * @return assess_token 示例：
     */
    public static String getAuth(String clientId, String clientSecret, RedisTemplate redisTemplate) {
        String token = "";
        if (!ObjectUtils.isEmpty(redisTemplate.opsForValue().get(XzConfig.getRedisPrefix()+"token"))) {
            log.info("access_token----", token);
            token = String.valueOf(redisTemplate.opsForValue().get(XzConfig.getRedisPrefix()+"token"));
            return token;
        }
        // 获取token地址
        String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
        String getAccessTokenUrl = authHost
                // 1. grant_type为固定参数
                + "grant_type=client_credentials"
                // 2. 官网获取的 API Key
                + "&client_id=" + clientId
                // 3. 官网获取的 Secret Key
                + "&client_secret=" + clientSecret;
        try {
            URL realUrl = new URL(getAccessTokenUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.err.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String result = "";
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            /**
             * 返回结果示例
             */
            System.err.println("result:" + result);
            JSONObject jsonObject = JSON.parseObject(result);
            String access_token = jsonObject.getString("access_token");
            redisTemplate.opsForValue().set(XzConfig.getRedisPrefix()+"token", access_token, 60 * 60 * 24, TimeUnit.SECONDS);
            log.info("access_token----", token);
            return access_token;
        } catch (Exception e) {
            System.err.printf("获取token失败！");
            throw new ServiceException("识别身份证失败");
        }
    }


    /**
     * 身份证识别
     *
     * @param path 本地图片路径
     * @return
     */
    public static String idCard(String path, String clientId, String clientSecret, RedisTemplate redisTemplate) {
        // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard";
        try {
            // 本地文件路径
            String filePath = path;
//            String newFilePath = getNewFilePath(filePath);
            String newFilePath = PicUtils.commpressPicForScale(filePath,PicUtils.setFileName(filePath), 3800, 0.8,4096,4096);
            byte[] imgData = FileUtil.readFileByBytes(newFilePath);
            String imgStr = Base64Util.encode(imgData);
            String imgParam = URLEncoder.encode(imgStr, "UTF-8");

            String param = "id_card_side=" + "front" + "&image=" + imgParam;

            // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
            String accessToken = getAuth(clientId, clientSecret, redisTemplate);

            String result = HttpUtil.post(url, accessToken, param);
            return result;
        } catch (Exception e) {
            throw new ServiceException("解析身份证失败");
        }
    }

    /**
     * 解析身份证json
     *
     * @param json
     * @return
     */
    public static Map parseIdCard(String json,Integer type) {
        Map result = new HashMap<>();
        Map map = JSON.parseObject(json, Map.class);
        try {
        Map wordsResult = JSON.parseObject(String.valueOf(map.get("words_result")));

            //身份证正面
            if(type==1){
                Map nameMap = JSON.parseObject(String.valueOf(wordsResult.get("姓名")), Map.class);
                Map sexMap = JSON.parseObject(String.valueOf(wordsResult.get("性别")), Map.class);
                Map idCardMap = JSON.parseObject(String.valueOf(wordsResult.get("公民身份号码")), Map.class);
                Map addressMap = JSON.parseObject(String.valueOf(wordsResult.get("住址")), Map.class);
                result.put("name", nameMap.get("words"));
                result.put("sex", sexMap.get("words"));
                result.put("idCard", idCardMap.get("words"));
                result.put("address", addressMap.get("words"));
            }else if(type==2){
                //身份证反面
                Map endMap = JSON.parseObject(String.valueOf(wordsResult.get("失效日期")), Map.class);
                Map startMap = JSON.parseObject(String.valueOf(wordsResult.get("签发日期")), Map.class);
                result.put("endTime", endMap.get("words"));
                result.put("startTime", startMap.get("words"));
            }
        }catch (Exception e){
            log.error(json);
            return null;

        }
        return result;
    }

    /**
     * 驾驶证识别
     *
     * @param path 本地图片路径
     * @return
     */
    public static String drivingLicense(String path, String clientId, String clientSecret, RedisTemplate redisTemplate) {
        // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/driving_license";
        try {
            // 本地文件路径
            String filePath = path;
//            String newFilePath = getNewFilePath(filePath);
            String newFilePath = PicUtils.commpressPicForScale(filePath,PicUtils.setFileName(filePath), 3800, 0.8,4096,4096);
            byte[] imgData = FileUtil.readFileByBytes(newFilePath);
            String imgStr = Base64Util.encode(imgData);
            String imgParam = URLEncoder.encode(imgStr, "UTF-8");

            String param = "image=" + imgParam;

            // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
            String accessToken = getAuth(clientId, clientSecret, redisTemplate);

            String result = HttpUtil.post(url, accessToken, param);
            return result;
        } catch (Exception e) {
            throw new ServiceException("解析驾驶证失败");
        }
    }

    /**
     * 压缩图片
     * @param filePath
     * @return
     */
    private static String getNewFilePath(String filePath) {
        long time = Timestamp.valueOf(LocalDateTime.now()).getTime();
        //前缀
        String prefix = filePath.substring(0,filePath.lastIndexOf("."));
        //后缀
        String suffix = filePath.substring(filePath.lastIndexOf("."));
        //拼接新的图片路径
        String newFilePath = prefix+"_"+time+suffix;
        // 压缩图片
        try {
            Thumbnails.of(filePath).scale(1f).outputQuality(0.5f).toFile(newFilePath);
        } catch (IOException e) {
            throw new ServiceException("解析失败");
        }
        return newFilePath;
    }

    /**
     * 解析驾驶证json
     *
     * @param json
     * @return
     */
    public static Map parseDrivingCard(String json) {
        Map result = new HashMap<>();
        Map map = JSON.parseObject(json, Map.class);
        try {

//            {"words_result":{"姓名":{"words":"陈文亮"},"有效起始日期":{"words":"20201206"},"出生日期":{"words":"19840112"},"证号":{"words":"350128198401124011"},"住址":{"words":"福建省平潭县潭城镇农中398号1幢201室"},"发证单位":{"words":"上海市公安局交通警察总队"},"初次领证日期":{"words":"20041206"},"国籍":{"words":"中国"},"准驾车型":{"words":"C1"},"性别":{"words":"男"},"有效期限":{"words":"长期"}},"direction":3,"words_result_num":11,"log_id":1668162282085127126}
//            {"words_result":{"姓名":{"words":"刘小龙"},"至":{"words":"20230528"},"出生日期":{"words":"19860616"},"证号":{"words":"500226198606163111"},"住址":{"words":"重庆市荣昌县古昌镇金鱼村3组78号"},"发证单位":{"words":"重庆市公安局交通管理局"},"初次领证日期":{"words":"20070528"},"国籍":{"words":"中国"},"准驾车型":{"words":"C1E"},"性别":{"words":"男"},"有效期限":{"words":"20130528"}},"direction":3,"words_result_num":11,"log_id":1668173626962259975}

            Map wordsResult = JSON.parseObject(String.valueOf(map.get("words_result")));
            Map driverType = JSON.parseObject(String.valueOf(wordsResult.get("准驾车型")), Map.class);
            Map cardNo = JSON.parseObject(String.valueOf(wordsResult.get("证号")), Map.class);

            result.put("driverType", driverType.get("words"));
            result.put("driverNo", cardNo.get("words"));

            Map validPeriod = JSON.parseObject(String.valueOf(wordsResult.get("有效期限")), Map.class);
            if("长期".equals(validPeriod.get("words"))){
                Map startTime = JSON.parseObject(String.valueOf(wordsResult.get("有效起始日期")), Map.class);
                result.put("startTime", startTime.get("words"));
                result.put("endTime", "21991231");
            }else{
                Map startTime = JSON.parseObject(String.valueOf(wordsResult.get("有效期限")), Map.class);
                Map endTime = JSON.parseObject(String.valueOf(wordsResult.get("至")), Map.class);
                result.put("startTime", startTime.get("words"));
                result.put("endTime", endTime.get("words"));
            }
        }catch (Exception e){
            log.error("解析驾驶证失败,err=>"+e);
            throw new ServiceException("解析驾驶证失败");
        }
        return result;
    }

    /**
     * 行驶证识别
     *
     * @param path 本地图片路径
     * @return
     */
    public static String registerLicense(String path, String clientId, String clientSecret, RedisTemplate redisTemplate) {
       // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/vehicle_license";
        try {
            // 本地文件路径
            String filePath = path;
//            String newFilePath = getNewFilePath(filePath);
            String newFilePath = PicUtils.commpressPicForScale(filePath,PicUtils.setFileName(filePath), 3800, 0.8,4096,4096);
            byte[] imgData = FileUtil.readFileByBytes(newFilePath);
            String imgStr = Base64Util.encode(imgData);
            String imgParam = URLEncoder.encode(imgStr, "UTF-8");

            String param = "image=" + imgParam;

            // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
            String accessToken = getAuth(clientId, clientSecret, redisTemplate);

            String result = HttpUtil.post(url, accessToken, param);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("解析行驶证失败");
        }
    }


    /**
     * 解析行驶证json
     *
     * @param json
     * @return
     */
    public static Map parseRegisterCard(String json) {
        try {
            Map result = new HashMap<>();
            Map map = JSON.parseObject(json, Map.class);
            Map wordsResult = JSON.parseObject(String.valueOf(map.get("words_result")));

            Map carModelNo = JSON.parseObject(String.valueOf(wordsResult.get("品牌型号")), Map.class);
            Map licenseDate = JSON.parseObject(String.valueOf(wordsResult.get("发证日期")), Map.class);
            Map engineNo = JSON.parseObject(String.valueOf(wordsResult.get("发动机号码")), Map.class);
            Map carPlateNo = JSON.parseObject(String.valueOf(wordsResult.get("号牌号码")), Map.class);
            Map carOwner = JSON.parseObject(String.valueOf(wordsResult.get("所有人")), Map.class);
            Map carOwnerAddr = JSON.parseObject(String.valueOf(wordsResult.get("住址")), Map.class);
            Map registerDate = JSON.parseObject(String.valueOf(wordsResult.get("注册日期")), Map.class);
            Map vinNo = JSON.parseObject(String.valueOf(wordsResult.get("车辆识别代号")), Map.class);
            Map carType = JSON.parseObject(String.valueOf(wordsResult.get("车辆类型")), Map.class);
            Map useType = JSON.parseObject(String.valueOf(wordsResult.get("使用性质")), Map.class);
            DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            DateFormat formatStr = new SimpleDateFormat("yyyy-MM-dd");
            result.put("carModelNo", carModelNo.get("words"));
            result.put("licenseDate", formatStr.format(dateFormat.parse(licenseDate.get("words").toString())));
            result.put("engineNo", engineNo.get("words"));
            result.put("carPlateNo", carPlateNo.get("words"));
            result.put("carOwner", carOwner.get("words"));
            result.put("carOwnerAddr", carOwnerAddr.get("words"));
            result.put("registerDate", formatStr.format(dateFormat.parse(registerDate.get("words").toString())));
            result.put("vinNo", vinNo.get("words"));
            result.put("carType", carType.get("words"));
            result.put("useType", useType.get("words"));
            return result;
        } catch (Exception e) {
            throw new ServiceException("解析行驶证失败!");
        }

    }


    public static void main(String[] args) {

        File srcfile = new File("/Users/zhangyan/Documents/jiashizheng.jpeg");
        File distfile = new File("/Users/zhangyan/Documents/jiashizheng1.jpeg");
        System.out.println("压缩前图片大小：" + srcfile.length());
        try {
            Thumbnails.of(srcfile).scale(1f).outputQuality(0.5f).toFile(distfile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("压缩后图片大小：" + distfile.length());
    }




}
